import React, { ReactNode, useState } from 'react'
import * as auth from 'auth-provider'
import { User } from 'screens/project-list/search-panel'
import { http } from 'utils/http'
import { useMount } from 'utils'
import { useAsync } from 'utils/use-async'
import { FullPageErrorFallback, FullPageLoading } from 'components/lib'

interface AuthForm {
  username: string,
  password: string
}

async function bootstrapUser() {
  let user = null
  const token = auth.getToken()
  if (token) {
    const data = await http('me', {token})
    user = data.user
  }
  return user
}

const AuthContext = React.createContext<{
  user: User|null,
  login: (form: AuthForm) => Promise<void>,
  register: (form: AuthForm) => Promise<void>,
  logout: () => Promise<void>
} | undefined>(undefined)
AuthContext.displayName = 'AuthContext'

export function AuthProvider({children}: {children: ReactNode}) {
  const {data: user, error, isLoading, isIdle, isError, run, setData: setUser} = useAsync<User|null>()

  function login(form: AuthForm) {
    return auth.login(form).then(setUser)
  }
  function register(form: AuthForm) {
    return auth.register(form).then(setUser)
  }
  function logout() {
    return auth.logout().then(() => setUser(null))
  }

  useMount(() => {
    run(bootstrapUser())
  })

  if (isIdle || isLoading) {
    return <FullPageLoading/>
  }

  if (isError) {
    return (<FullPageErrorFallback error={error}/>)
  }

  return (<AuthContext.Provider children={children} value={{user, login, register, logout}} />)
}

export function useAuth() {
  const context = React.useContext(AuthContext)
  if (!context) {
    throw new Error('useAuth必须在AuthProvider中使用')
  }
  return context
}
